'''
Created on Aug 3, 2011

@author: Andrey Razhanskiy
'''
from sgmllib import SGMLParser
import re
import datetime
class OFX(object):pass
class OFXNode(object):pass

class OFXParser(object):

    def parse(self, file_handle):
        body  = file_handle.read()
        body  = body[body.index("<OFX>"):]
        self.is_bank = body.find('<BANKMSGSRSV1>') > 0
        self.tags = self._get_nodes(body.replace("\n",""))
        self._build_tree()
        self._postprocess()
        
    def _postprocess(self):
        try:
            self.ofx.creditcardmsgsrsv1.ccstmttrnrs
            self.ofx.creditcardmsgsrsv1.ccstmttrnrss = [self.ofx.creditcardmsgsrsv1.ccstmttrnrs]
        except:
            pass
            
    def _get_nodes(self, str):
        nodes = []
        for token in re.split("<", str):
            if token.find(">") > -1:
                nodes.append([tok.strip() for tok in re.split(">", token)])
        return nodes

    def _build_tree(self,):
        self.pos = len(self.tags) - 1
        name , self.ofx  = self._build_node()
        pass

    def _build_node(self):
        node = OFXNode()
        (tag_name, value) = self.tags[self.pos]
        tag_name = tag_name[1:]
        self.pos = self.pos - 1 
        (name, value) = self.tags[self.pos]
        while name != tag_name:
            if name[0] == "/":
                (name, value) = self._build_node()
            self._set_attr(node,name.lower(),value)
            self.pos = self.pos - 1 
            (name, value) = self.tags[self.pos]
        return tag_name,node

    def _set_attr(self, node, name, value):
        names = name + "s"
        prev_val = getattr(node, name, None)
        if prev_val:
            setattr(node,names,[prev_val,value])
            delattr(node, name)
            return
        is_array = getattr(node, names, None)
        if is_array:
            is_array.insert(0,value)
            return
        setattr(node,name,value)
    
    def get_account(self):
        if self.is_bank:
            return self.ofx.bankmsgsrsv1.stmttrnrs.stmtrs.bankacctfrom.acctid
        else:
            return self.ofx.creditcardmsgsrsv1.ccstmttrnrss[0].ccstmtrs.ccacctfrom.acctid



    def get_account_type(self):
        if self.is_bank:
            return self.ofx.bankmsgsrsv1.stmttrnrs.stmtrs.bankacctfrom.accttype
        else:
            return "CREDIT"


    def get_transactions(self):
        ret = []
        if self.is_bank:
            ret = self.ofx.bankmsgsrsv1.stmttrnrs.stmtrs.banktranlist.stmttrns
        else:
            for statement in self.ofx.creditcardmsgsrsv1.ccstmttrnrss: 
                [ret.append(trans) for trans in statement.ccstmtrs.banktranlist.stmttrns]
        for tran in ret:
            # join name and memo if name is not same as memo                
            try: 
                if tran.memo.find(tran.name) == -1:
                    tran.name = tran.name + tran.memo 
            except: 
                tran.memo = ""
                
            tran.dtposted = datetime.datetime.strptime(tran.dtposted[0:8] , "%Y%m%d")
        return ret